[小ネタ]Lambda統合を使用したAPI Gatewayのエクスポート→インポートの注意点
はじめに
API Gatewayをドキュメントで管理したり、他のリージョンやAWSアカウントに移行したりする時の便利な機能としてAPIをエクスポートできます。インポートする時もエクスポートしたAPIドキュメントをインポートするだけでAPIをデプロイできるようになります。
エクスポートの形式の選択肢として、「API Gateway拡張の形式」が選択できます。これは、Lambda統合やAWSサービスが設定されているAPIをエクスポートするのに有効な形式です。なのでLambda統合されたAPIドキュメントをインポートしてデプロイすれば使える、、というわけではありません。API GatewayからLambdaをInvokeできる権限(lambda:InvokeFunction)が必要です。
インポートはできているが、InternalServerError
例として、ユーザガイドを参考にLambda統合されたREST APIを作成しました。
統合リクエストでは、Hello from Lambda!
を返すだけのLambda関数を設定します。
Lambda関数を指定してチェックすると以下のポップアップがでてきます。「OK」することでAPI GatewayからLambda関数を呼び出すことができるようになります。
APIをデプロイしてAPIにアクセスすると"Hello from Lambda!"
が返ってきます。このAPIを「Swagger + API Gateway拡張の形式」でエクスポートします。
APIドキュメント内は、以下の通りです。
---
swagger: "2.0"
info:
version: "2020-10-XXTXX:XX:XXZ"
title: "test-api-gw"
host: "xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com"
basePath: "/dev"
schemes:
- "https"
paths:
/:
get:
produces:
- "application/json"
responses:
200:
description: "200 response"
schema:
$ref: "#/definitions/Empty"
x-amazon-apigateway-integration:
uri: "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:test/invocations"
responses:
default:
statusCode: "200"
passthroughBehavior: "when_no_match"
httpMethod: "POST"
contentHandling: "CONVERT_TO_TEXT"
type: "aws_proxy"
definitions:
Empty:
type: "object"
title: "Empty Schema"
titleをtest-api-gw-import
に変更してインポートしてみます。エクスポート先とインポート先のAWSアカウントは同一で試しています。
APIドキュメント通りです。デプロイしてAPIにアクセスしてみます。
{"message": "Internal server error"}
が返ってきました。GETメソッドをテストしてみるとステータスが500で返されます。ログを見るとExecution failed due to configuration error: Invalid permissions on Lambda function
が出力されています。インポートされたAPIには、Lambda関数が設定されていても呼び出す権限がありません。
明示的に権限を付与(手動)
明示的に権限を付与する必要があります。
上記のLambda関数を再度選んで右側にあるチェックするとAPIを作成した時の同様のポップアップが出てくるので「OK」します。権限が付与されたのでもう一度テストしてみると成功しました。
明示的に権限を付与(IAMロール)
この権限はインポート時には気づきにくい点であり、多数のLambda統合されたメソッドに対して設定するには面倒です。なので実行ロールを設定することで、明示的に許可することで上記のようなインポート後の設定が不要になります。
IAMポリシーを作成します。必要なアクションは、lambda:InvokeFunction
です。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": "*"
}
]
}
次にIAMロールを作成します。信頼関係をAPI Gatewayで設定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
このIAMロールをエクスポート元のAPIに設定し、エクスポートしたファイルが以下です。
---
swagger: "2.0"
info:
version: "2020-10-XXTXX:XX:XXZ"
title: "test-api-gw"
host: "xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com"
basePath: "/dev"
schemes:
- "https"
paths:
/:
get:
produces:
- "application/json"
responses:
200:
description: "200 response"
schema:
$ref: "#/definitions/Empty"
x-amazon-apigateway-integration:
type: "aws_proxy"
credentials: "arn:aws:iam::xxxxxxxxxxxx:role/lambda-invoke"
uri: "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:x:function:txxxxxxxxxxxest/invocations"
responses:
default:
statusCode: "200"
passthroughBehavior: "when_no_match"
httpMethod: "POST"
contentHandling: "CONVERT_TO_TEXT"
definitions:
Empty:
type: "object"
title: "Empty Schema"
x-amazon-apigateway-integrationオブジェクトにcredentialsが追加されました。設定したIAMロールでLambda関数が呼び出しできます。このAPIドキュメントを再度インポートしてみます。今度は実行ロールが設定されています。
テストしてみると今度は成功しました。
まとめ
Lambda統合されたAPIをインポートする時の権限に関するご案内でした。AWSサービスと統合されたAPIドキュメントを管理する場合の参考になれば幸いです。